
package com.grace.redis.config;

import java.nio.charset.Charset;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.Filter;

/**
 * Redis使用FastJson序列化。注意：此实现考虑了安全性、性能和可维护性的平衡。
 * 
 * @author grace
 * @param <T> 序列化和反序列化的对象类型
 */
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {

    // 将字符集和过滤器作为构造函数参数，提高可配置性和可维护性
    private final Charset charset;
    private final Filter autoTypeFilter;
    private final Class<T> clazz;

    /**
     * 构造函数，接收序列化类型、字符集和自动类型过滤器。
     * 
     * @param clazz          序列化和反序列化的对象类型
     * @param charset        使用的字符集
     * @param autoTypeFilter 自动类型过滤器，为null则不启用
     */
    public FastJson2JsonRedisSerializer(Class<T> clazz, Charset charset, Filter autoTypeFilter) {
        this.clazz = clazz;
        this.charset = charset != null ? charset : Charset.forName("UTF-8");
        this.autoTypeFilter = autoTypeFilter != null
                ? autoTypeFilter
                : JSONReader.autoTypeFilter("org.springframework", "com.grace", "java.util");
    }

    /**
     * 序列化方法，将对象转换为JSON字节数组。
     * 
     * @param t 待序列化的对象
     * @return 序列化后的字节数组
     * @throws SerializationException 序列化过程中发生异常
     */
    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        // 使用提供的字符集进行序列化
        return JSON.toJSONString(t, autoTypeFilter, JSONWriter.Feature.WriteClassName).getBytes(charset);
    }

    /**
     * 反序列化方法，将字节数组转换为对象。
     * 
     * @param bytes 待反序列化的字节数组
     * @return 反序列化后的对象
     * @throws SerializationException 反序列化过程中发生异常
     */
    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        try {
            String str = new String(bytes, charset);
            // 使用白名单过滤器，避免直接启用 SupportAutoType
            return JSON.parseObject(str, clazz, autoTypeFilter);
        } catch (Exception e) {
            throw new SerializationException("Failed to deserialize due to invalid JSON format or other issues.", e);
        }
    }
}